// db_mysql.cpp: implementation of the db_mysql class.
//
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "db_mysql.h"
#include "Log.h"

#ifdef WIN32
#pragma comment(lib,"libmysql")
#endif

/*
create table svusers(username char(16) not null primary key, password char(16) not null,
					realname char(10) not null,idcardno char(15) not null,phoneno char(16) not null,
					address char(40) not null,type int(2) not null,opendate date not null);

+----------+----------+------+-----+------------+-------+
| Field    | Type     | Null | Key | Default    | Extra |
+----------+----------+------+-----+------------+-------+
| username | char(16) |      | PRI |            |       |
| password | char(16) |      |     |            |       |
| realname | char(10) |      |     |            |       |
| idcardno | char(15) |      |     |            |       |
| phoneno  | char(16) |      |     |            |       |
| address  | char(40) |      |     |            |       |
| type     | int(2)   |      |     | 0          |       |
| opendate | date     |      |     | 0000-00-00 |       |
+----------+----------+------+-----+------------+-------+
*/
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

db_mysql::db_mysql()
{
	m_bInited = false;
	m_bConnected = false;
	m_sHost[0] = '\0';
	m_sUserName[0] = '\0';
	m_sPassword[0] = '\0';
	m_sDBName[0] = '\0';
	m_nPort = 0;
	m_nRows_Readed = 0;
	m_sUnix_Socket[0] = '\0';
	m_nClient_Flag = 0;
	m_pMySQL_RES = NULL;
}

db_mysql::~db_mysql()
{
	if(m_bInited)
	{
		mysql_close(&m_MySQL);
		m_bInited = false;
	}
}

int db_mysql::connect(const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned int client_flag)
{
	char *p;
	if(!m_bInited)
		return -1;
	if(!mysql_real_connect(&m_MySQL, host, user, passwd, db, port, unix_socket,client_flag))	
	{
		p = (char *)mysql_error(&m_MySQL);
		Loger.printf(LOG_ERROR,"%s",p);
		strcpy(m_sLastError,p);
		return -1;
	}
    my_bool re_conn = true;
    mysql_options(&m_MySQL, MYSQL_OPT_RECONNECT, &re_conn);
		
	m_bConnected = true;
	if(host)
		strcpy(m_sHost,host);
	if(user)
		strcpy(m_sUserName,user);
	if(passwd)
		strcpy(m_sPassword,passwd);
	if(db)
		strcpy(m_sDBName,db);
	m_nPort = port;
	if(unix_socket)
		strcpy(m_sUnix_Socket,unix_socket);
	m_nClient_Flag = client_flag;
	return 0;	
}
int db_mysql::init()
{
	if(m_bInited)
		return -2;
	if(!mysql_init(&m_MySQL))
		return -1;
	m_bInited = true;
	m_nRows_Readed = 0;
	return 0;	
}

int db_mysql::open_db(const char *db)
{
	if(!m_bConnected)
		return -1;
	if(mysql_select_db(&m_MySQL,db))
		return -1;
	if(db)
	{
		strcpy(m_sDBName,db);
	}
	else
		m_sDBName[0] = '\0';
	return 0;	
}

int db_mysql::exec_sql(const char *sql)
{
	char *p;
	if(!m_bConnected || sql == NULL)
	{
		strcpy(m_sLastError,"mysql not connected");
		return -1;
	}
	p = strstr(sql,"SELECT");
	if(p == NULL)
		p = strstr(sql,"select");
	if(p)
		m_nRows_Readed = 0;

	if(mysql_real_query(&m_MySQL, sql, strlen(sql) ) )
	{
	    // error cause by 2 reasons: sql error, or connection lost
	    //                           
        if(mysql_ping(&m_MySQL) != 0)
       {
	        strcpy(m_sLastError, mysql_error(&m_MySQL));
		    return -1;     
        }
        //run to here, mean, the connection is OK.
        if(mysql_real_query(&m_MySQL, sql, strlen(sql) ) )
        {
            strcpy(m_sLastError, mysql_error(&m_MySQL));
		    return -1;     
        }
		
	}
	if(m_pMySQL_RES)
		mysql_free_result(m_pMySQL_RES);
	m_pMySQL_RES = mysql_store_result(&m_MySQL);	
	return 0;
}

void db_mysql::print_rows()
{
	MYSQL_ROW row;
	unsigned int num_fields;
	unsigned int i;
	if(m_pMySQL_RES == NULL)
		return;
	num_fields = mysql_num_fields(m_pMySQL_RES);
	while ((row = mysql_fetch_row(m_pMySQL_RES)))
	{
		unsigned long *lengths;
		lengths = mysql_fetch_lengths(m_pMySQL_RES);
		for(i = 0; i < num_fields; i++)
		{
			printf("[%.*s]", (int) lengths[i], row[i] ? row[i] : "NULL");
		}
		printf("\n");		
	}
}

unsigned long db_mysql::rows()
{
	if(m_pMySQL_RES)
		return mysql_num_rows(m_pMySQL_RES);
	else
		return 0;
}

int db_mysql::getnextuser(char *username, char *password, char *realname, char *idcardno, char *phoneno, char *address, int &type, char *opendate)
{
	MYSQL_ROW row;
	unsigned int num_fields;
	if(m_pMySQL_RES == NULL)
		return -1;
	num_fields = mysql_num_fields(m_pMySQL_RES);
	if((row = mysql_fetch_row(m_pMySQL_RES)))
	{
		unsigned long *lengths;
		lengths = mysql_fetch_lengths(m_pMySQL_RES);
		char buf[20];
		//for(i = 0; i < num_fields; i++)
		{
			sprintf(username,"%.*s", (int) lengths[0], row[0] ? row[0] : "NULL");
			sprintf(password,"%.*s", (int) lengths[1], row[1] ? row[1] : "NULL");
			sprintf(realname,"%.*s", (int) lengths[2], row[2] ? row[2] : "NULL");
			sprintf(idcardno,"%.*s", (int) lengths[3], row[3] ? row[3] : "NULL");
			sprintf(phoneno ,"%.*s", (int) lengths[4], row[4] ? row[4] : "NULL");
			sprintf(address ,"%.*s", (int) lengths[5], row[5] ? row[5] : "NULL");
			sprintf(buf     ,"%.*s", (int) lengths[6], row[6] ? row[6] : "NULL");
			type = atoi(buf);
			sprintf(opendate,"%.*s", (int) lengths[7], row[7] ? row[7] : "NULL");
			m_nRows_Readed++;
		}		
		return 0;
	}
	else
		return -1;
}
int db_mysql::getupperuser(char *username, char *password, char *realname, char *idcardno, char *phoneno, char *address, int &type, char *opendate)
{	
	if(m_pMySQL_RES == NULL)
		return -1;
	//num_fields = mysql_num_fields(m_pMySQL_RES);
	MYSQL_ROW_OFFSET offset = mysql_row_tell(m_pMySQL_RES);
	if(m_nRows_Readed >1)
	{
		m_nRows_Readed-=2;
		mysql_data_seek(m_pMySQL_RES,m_nRows_Readed);
		return getnextuser(username, password, realname,idcardno, phoneno, address, type, opendate);

	}
	else
	{
		return -1;
	}
}

int db_mysql::selectdb(const char *pdb)
{
	return mysql_select_db(&m_MySQL, pdb);
}

void db_mysql::close()
{
	mysql_close(&m_MySQL);
	m_bInited = false;
	m_bConnected = false;

}

MYSQL_ROW db_mysql::next()
{	
	if(m_pMySQL_RES == NULL)
		return 0;
	return mysql_fetch_row(m_pMySQL_RES);
}
void db_mysql::seek(unsigned long pos)
{
	mysql_data_seek(m_pMySQL_RES,pos);	
}
